/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.helsoft.mojo.api;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;

import org.apache.maven.plugin.logging.Log;

/**
 * 
 * @author steg
 */
public class JarCreator {

	private static String cat(String[] array, int length) {
		String _rep = "";
		for (int _i = 0; _i < length; ++_i) {
			_rep += array[_i].trim();
			if (_i != length - 1) {
				_rep += "/";
			}
		}
		return _rep;
	}
	
	private static byte[] readBytes(File file, Log log) throws IOException {
		byte[] buffer = new byte[(int) file.length()];
		DataInputStream dos = new DataInputStream(new FileInputStream(file));
		dos.readFully(buffer);
		dos.close();
		return buffer;
	}

	private static void addFolderEntry(JarOutputStream _zos, String[] dir, Integer pos,
			File file, Log log) throws IOException {
		File[] list = file.listFiles();
		for (int _i = 0; _i < list.length; ++_i) {
			if (list[_i].isFile()) {
				String _path = (pos > 0 ? (cat(dir, pos) + "/") : "") + list[_i].getName();
				log.debug("Adding " + _path);
				byte[] buffer = readBytes(list[_i], log);
				_zos.putNextEntry(new JarEntry(_path));
				_zos.write(buffer);
				_zos.closeEntry();
			} else if (list[_i].isDirectory()) {
				dir[pos++] = list[_i].getName();
				addFolderEntry(_zos, dir, pos, list[_i], log);
				--pos;
			}
		}
	}

	private static void addFileEntry(JarOutputStream zos, File source, Log log)
			throws IOException {
		log.debug("Adding " + source.getName());
		zos.putNextEntry(new JarEntry(source.getName()));
		byte[] buf = readBytes(source, log);
		zos.write(buf);
		zos.closeEntry();
	}

	/**
	 * Jar a folder
	 * 
	 * @param source
	 *            The source folder
	 * @param destination
	 *            The destination file
	 * @throws java.io.IOException
	 */
	public static void folderToJar(File source, File destination,
			boolean preservePath, Log log) throws IOException {
		if (!source.isDirectory()) {
			throw new IOException(" No such folder " + source.getPath());
		}
		JarOutputStream zos = null;
		try {
			zos = new JarOutputStream(new FileOutputStream(destination));
			String[] name = new String[50];
			Integer pos = 0;
			if (preservePath) {
//				name[pos++] = source.getName();
				addFolderEntry(zos, name, pos, source, log);
			} else {
				for (File f : source.listFiles()) {
					if (f.isDirectory()) {
						Arrays.fill(name, "");
						name[0] = f.getName();
						pos = 1;
						addFolderEntry(zos, name, pos, f, log);
					} else {
						addFileEntry(zos, f, log);
					}
				}
			}
		} finally {
			if (zos != null) {
				zos.finish();
				zos.close();
			}
		}
	}

	/**
	 * Jarper un fichier
	 * 
	 * @param source
	 *            Le fichier source
	 * @param destination
	 *            Le fichier destination
	 * @throws java.io.IOException
	 */
	public static void fileToJar(File source, File destination, Log log)
			throws IOException {
		if (!source.isFile()) {
			throw new IOException(" No  such file " + source.getPath());
		}
		JarOutputStream zos = null;
		try {
			zos = new JarOutputStream(new FileOutputStream(destination));
			log.debug("Adding " + source.getCanonicalPath());
			addFileEntry(zos, source, log);
		} finally {
			zos.finish();
			zos.close();
		}
	}

	/**
	 * @param source
	 *            Le fichier source
	 * @throws java.io.IOException
	 */
	public static void makeJar(File source, Log log) throws IOException {
		if (source.isDirectory()) {
			folderToJar(source, new File(source.getName() + ".jar"), true, log);
		} else if (source.isFile()) {
			fileToJar(source, new File(source.getName() + ".jar"), log);
		}
	}

}
